import 'dart:collection';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:x3_base_core/x3_base_core.dart';
import 'package:x3_component_core/x3_component_core.dart';

class BaseRefreshComponent extends StatefulWidget {
  /// 请求的服务地址
  final String path;

  /// 请求的方式
  final BaseHttpMethodEnum method;

  /// 构建Item项
  final Widget Function(Map<String, dynamic> item, int index) buildItem;

  /// 构建 separator
  final Widget Function(Map<String, dynamic> item) separatorBuilder;

  /// 是否是分页查询
  final bool isPaging;

  /// 刷新列表控制器
  final BaseRefreshController controller;

  /// 参数
  final Map<String, dynamic> params;

  /// 刷新数据加载完成事件
  final Function(List<Map<String, dynamic>> items) refreshDataLoadComplete;

  /// Loading加载完成事件 上拉加载专用，将每次加载到的数据回传
  final Function(List<Map<String, dynamic>> items) dataLoadComplete;

  /// 内边距
  final EdgeInsets padding;

  /// 预加载
  final double cacheExtent;

  /// 是否默认加载数据
  final bool autoLoad;

  /// 每页显示多少条数
  final int pageSize;

  /// 数组是更下一层 的 key
  final String nextLevelKey;

  /// 列表顶部的Widget
  final Widget headerWidget;

  /// 是否使用默认的[headerWidget],但这不会覆盖[headerWidget]
  final bool needDefaultHeaderWidget;

  /// 请求类型
  final BaseRefreshServiceType serviceType;

  /// 由于有多个请求类型，每个类型的返回数据还不一定一样，过于奇葩，只能将数据整理对外，让外部处理
  /// 如果不为null 则调用，否则按照默认处理
  final List<dynamic> Function(BaseHttpResultModel result) initResultData;

  BaseRefreshComponent({
    Key key,
    @required this.path,
    @required this.buildItem,
    this.controller,
    this.padding = EdgeInsets.zero,
    this.separatorBuilder,
    this.method = BaseHttpMethodEnum.POST,
    this.serviceType = BaseRefreshServiceType.Fetch,
    this.isPaging = true,
    this.refreshDataLoadComplete,
    this.dataLoadComplete,
    this.params = const {},
    this.cacheExtent,
    this.pageSize = 15,
    this.nextLevelKey,
    this.headerWidget,
    this.initResultData,
    this.autoLoad = true,
    this.needDefaultHeaderWidget = false,
  }) : super(key: key);

  @override
  _BaseRefreshComponentState createState() => _BaseRefreshComponentState();
}

class _BaseRefreshComponentState extends State<BaseRefreshComponent> {
  /// 当前是第几页
  int pageIndex = 1;

  /// 获取当前的控制器
  BaseRefreshController _effectiveController;

  /// 下拉刷新组件
  GlobalKey<RefreshIndicatorState> _refreshIndicatorState;

  @override
  void initState() {
    super.initState();
    _effectiveController = widget.controller ?? BaseRefreshController();
    _effectiveController.addListener(() {
      this._refreshIndicatorState.currentState.show();
    });
  }

  /// 获取数据
  Future<BaseHttpResultModel> _getItems() async {
    if (widget.path == null || widget.path.isEmpty) {
      return BaseHttpResultModel(BaseDioCodeUtil.success_code, true, [], null, null);
    }
    Map<String, dynamic> params = new HashMap();
    if (widget.params != null) params.addAll(widget.params);
    params.addAll(_effectiveController.params);
    if (widget.isPaging == true) {
      Map<String, dynamic> pageParams = {'pageIndex': pageIndex, 'pageSize': widget.pageSize};
      params.addAll(pageParams);
    }
    BaseHttpResultModel result = await this._fetchRequestData(params);
    return result;
  }

  /// 请求服务, 获取数据
  Future<BaseHttpResultModel> _fetchRequestData(dynamic params) {
    switch (widget.serviceType) {
      case BaseRefreshServiceType.Fetch:
        return dioUtil.fetch(widget.path, method: widget.method, params: params);
      case BaseRefreshServiceType.X2Microservice:
        return dioX2Util.fetchX2Microservice(widget.path, method: widget.method, params: params);
      case BaseRefreshServiceType.X3YJbService:
        return dioX2Util.fetchX3YjbService(widget.path, method: widget.method, params: params);
      case BaseRefreshServiceType.XML:
        return dioX2Util.fetchXMLService(widget.path, method: widget.method, params: params);
        break;
      default:
        return dioUtil.fetch(widget.path, method: widget.method, params: params);
    }
  }

  /// 刷新数据
  Future<List<Map<String, dynamic>>> _onRefresh() async {
    this.pageIndex = 1;
    BaseHttpResultModel result = await _getItems();
    List<dynamic> datas = [];
    if (widget.nextLevelKey != null) {
      if (result.success == true && result.data[widget.nextLevelKey] is List) datas = result.data[widget.nextLevelKey];
    } else {
      datas = this._initResultData(result);
    }
    List<Map<String, dynamic>> items = BaseDioCodeUtil.dynamicListToMapList(datas);
    if (widget.refreshDataLoadComplete != null) {
      widget.refreshDataLoadComplete(items);
    }
    return items;
  }

  /// 加载更多数据
  Future<List<Map<String, dynamic>>> _onLoading() async {
    this.pageIndex = this.pageIndex + 1;
    BaseHttpResultModel result = await _getItems();
    List<dynamic> datas = [];
    if (widget.nextLevelKey != null) {
      if (result.success == true && result.data[widget.nextLevelKey] is List) datas = result.data[widget.nextLevelKey];
    } else {
      datas = this._initResultData(result);
    }
    List<Map<String, dynamic>> items = BaseDioCodeUtil.dynamicListToMapList(datas);
    if (widget.dataLoadComplete != null) {
      widget.dataLoadComplete(items);
    }
    return items;
  }

  List<dynamic> _initResultData(BaseHttpResultModel result) {
    if (widget.initResultData != null) {
      return widget.initResultData(result);
    }
    if (result.success == true && result.data is List) {
      return result.data;
    } else if (result.success == true && result.data is Map) {
      dynamic success = BaseUtils.getKeyData(result.data, 'success');
      return success == true ? _getListDynamic(result.data) : [];
    }
    return [];
  }

  List<dynamic> _getListDynamic(dynamic data) {
    var _data = BaseUtils.getKeyData(data, 'data', defaultValue: []);
    if (_data is List) return _data;
    if (_data is String && _data.isNotEmpty) {
      try {
        dynamic dataDynamic = jsonDecode(_data);
        if (dataDynamic is Map && dataDynamic.containsKey('data') && dataDynamic['data'] is List) {
          return dataDynamic['data'];
        }
      } catch (e) {
        return [];
      }
    }
    return [];
  }

  @override
  Widget build(BuildContext context) {
    return BaseRefreshContainerComponent(
      builder: (BuildContext context, int index, dynamic item) => widget.buildItem(item, index),
      separatorBuilder: (BuildContext context, int index, dynamic item) {
        return widget.separatorBuilder != null ? widget.separatorBuilder(item) : SizedBox(height: 0);
      },
      getRefreshIndicatorState: (GlobalKey<RefreshIndicatorState> refreshIndicatorState) {
        this._refreshIndicatorState = refreshIndicatorState;
      },
      autoLoad: widget.autoLoad,
      needLoading: widget.isPaging,
      onRefresh: _onRefresh,
      onLoading: _onLoading,
      padding: widget.padding,
      cacheExtent: widget.cacheExtent,
      headerWidget: _headerWidget(),
    );
  }

  Widget _headerWidget() {
    if (widget.needDefaultHeaderWidget && widget.headerWidget == null) return _defaultHeaderWidget();
    return widget.headerWidget;
  }

  Widget _defaultHeaderWidget() {
    return Container(width: double.infinity, height: 12.0);
  }

  @override
  void dispose() {
    _effectiveController.dispose();
    super.dispose();
  }
}
